<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
   
</head>
<body>
    <script>
        
    

        //深拷贝2,解决问题：函数类型的属性丢失了，循环引用会报错
        {
            let oo={};
            let two=[22,2,22]
        const obj={a:"a",b:'b',c:{c1:'c1',c2:{c3:"c3"}},arr:[1,2,3],d:function(){},map:new Map([
  [oo, 'one'],
  [2, two],
  [3, 'three'],
]),set:new Set([1,2,3]),g:new RegExp(),h:new Error('挂了'),date:new Date()}

       // console.log(obj.valueOf());
        // 循环引用
        obj.e=obj.c;
        obj.c.e=obj.e
        const obj1=deepClone(obj);
        // obj1['a']='dada'
        // obj1['c'].c1='dada'
        // obj1.c.c2.c3='c3333'
        //obj1.arr[0]=1000
            obj1.map.set(oo,'11')
            obj1.set.add('hellokity')
        console.log('deepclone2')
        console.log(obj,obj1)
            // obj1.c.c1='ccc'
           
        // console.log(arr,arr1)
            /**
             * 需要考虑以下情况：
             * 1.null
             * 2.对象
             * 3.数组
             * 4.其它对象
             * 5.循环引用
             * 
            */
            function deepClone(obj,map=new Map()){
                
                if(obj===undefined) return undefined;
                if(obj===null) return null;
                if( typeof obj === 'object'){
                   
                    if(getType(obj)==='Object'){
                        const cache=map.get(obj);
                        if(cache){
                            return cache;
                        }
                       
                        // 对象处理
                        let res={};
                        // 先缓存res到map,然后后面res更新也会自动更新
                         map.set(obj,res)
                        // for(const key in obj){
                        //  if(obj.hasOwnProperty(key)){
                        //      res[key]=deepClone(obj[key])   
                        //     }
                        // }
                        Object.keys(obj).forEach(key=>{
                            res[key]=deepClone(obj[key],map) 
                        })
                        return res;
                    }
                    else if(getType(obj)==='Array'){
                        // 数组处理
                        let res=[];
                        console.log(obj)
                        obj.forEach((ele,index) => {
                            res[index]=deepClone(ele,map)
                        });
 
                      
                        return res;
                    }
                    else{
                        // 其它对象处理
                        console.log('其它',obj)
                        const constructor=obj.constructor;
                        // 通过构造器新建实例
                         return new constructor(obj.valueOf())
                        //return obj;
                    }
                   
                
                    
                }
                //基本类型 直接返回
                return obj
            }
            console.log(getType(obj))
            function getType(data){
                return Object.prototype.toString.call(data).slice(8,-1)
            }
    }

    </script>
    
</body>
</html>